﻿#region License
// Copyright 2010 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Diagnostics;
using System.Globalization;
using MediaWiki.Common;

namespace MediaWiki.MediaWikiConverter.Utilities.Logging
{
  public class LogTrace
  {
    private enum TraceState
    {
      NotStarted,
      Started,
      Completed
    }

    private TraceState _state;
    private Stopwatch _stopwatch;

    public string Message { get; private set; }
    public string Category { get; private set; }
    public bool Indent { get; private set; }

    public LogTrace(string message, string category, bool indent)
    {
      Message = message;
      Category = category;
      Indent = indent;
      _state = TraceState.NotStarted;
    }

    public void Start()
    {
      if (_state != TraceState.NotStarted)
        throw new Exception("Trace has already been started.");

      _state = TraceState.Started;

      if (!string.IsNullOrEmpty(Category))
        Trace.CorrelationManager.StartLogicalOperation(Category);

      Logger.Verbose("Trace Start: " + FormatMessage(Message, Category));

      if (Indent)
        Logger.Indent();

      _stopwatch = new Stopwatch();
      _stopwatch.Start();
    }

    public void Error(Exception ex)
    {
      ValidationUtils.ArgumentNotNull(ex, "ex");

      Logger.LogException(LogLevel.Error, "Trace Error: " + FormatMessage(Message, Category), ex, Category);
    }

    private string FormatMessage(string message, string category)
    {
      if (string.IsNullOrEmpty(category))
        return message;

      return category + " - " + message;
    }

    public void Complete()
    {
      if (_state != TraceState.Started)
        throw new Exception("Trace has not been started.");

      _state = TraceState.Completed;

      if (!string.IsNullOrEmpty(Category))
        Trace.CorrelationManager.StopLogicalOperation();

      if (Indent)
        Logger.Unindent();

      string elapsedTime = (_stopwatch != null) ? GetSecondsElapsed(_stopwatch.ElapsedMilliseconds).ToString(CultureInfo.InvariantCulture) : "n/a";

      Logger.Verbose("Trace End: {0} (elapsed time: {1} seconds)".FormatWith(FormatMessage(Message, Category), elapsedTime), Category);
    }

    private static decimal GetSecondsElapsed(long milliseconds)
    {
      decimal d = Convert.ToDecimal(milliseconds) / 1000M;
      return Math.Round(d, 6);
    }
  }
}